package com.example.blog.service.impl;


import com.example.blog.modules.article.dto.ArticleDTO;
import com.example.blog.modules.article.service.ArticleService;
import com.example.blog.modules.system.dto.DashboardStatsDTO;
import com.example.blog.modules.system.service.DashboardService;
import com.example.blog.repository.*;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.PageRequest;
import org.springframework.stereotype.Service;

import java.time.LocalDateTime;
import java.time.temporal.ChronoUnit;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

@Service
public class DashboardServiceImpl implements DashboardService {
    @Autowired
    private UserRepository userRepository;

    @Autowired
    private ArticleRepository articleRepository;

    @Autowired
    private CommentRepository commentRepository;

    @Autowired
    private ArticleService articleService;

    @Override
    public DashboardStatsDTO getDashboardStats() {
        DashboardStatsDTO stats = new DashboardStatsDTO();

        // Basic statistics
        stats.setTotalUsers(userRepository.count());
        stats.setTotalArticles(articleRepository.count());
        stats.setTotalComments(commentRepository.count());
        stats.setTotalViews(calculateTotalViews());

        // Popular and recent articles
        stats.setPopularArticles(getPopularArticles());
        stats.setRecentArticles(getRecentArticles());

        // Article statistics by status
        stats.setArticleStats(getArticleStats());

        // User registration statistics by month
        stats.setUserStats(getUserStats());

        // View statistics by day
        stats.setViewStats(getViewStats());

        return stats;
    }

    private long calculateTotalViews() {
        return articleRepository.findAll().stream()
                .mapToLong(article -> article.getViewCount())
                .sum();
    }

    private List<ArticleDTO> getPopularArticles() {
        return articleRepository.findTop5ByPublishedTrueOrderByViewCountDesc()
                .stream()
                .map(article -> {
                    ArticleDTO dto = new ArticleDTO();
                    dto.setId(article.getId());
                    dto.setTitle(article.getTitle());
                    dto.setViewCount(article.getViewCount());
                    return dto;
                })
                .collect(Collectors.toList());
    }

    private List<ArticleDTO> getRecentArticles() {
        return articleRepository.findTop5ByPublishedTrueOrderByCreatedAtDesc()
                .stream()
                .map(article -> {
                    ArticleDTO dto = new ArticleDTO();
                    dto.setId(article.getId());
                    dto.setTitle(article.getTitle());
                    dto.setCreatedAt(article.getCreatedAt());
                    return dto;
                })
                .collect(Collectors.toList());
    }

    private Map<String, Long> getArticleStats() {
        Map<String, Long> stats = new HashMap<>();
        long totalArticles = articleRepository.count();
        long publishedArticles = articleRepository.findByPublishedTrue(PageRequest.of(0, 1)).getTotalElements();
        
        stats.put("total", totalArticles);
        stats.put("published", publishedArticles);
        stats.put("draft", totalArticles - publishedArticles);
        
        return stats;
    }

    private Map<String, Long> getUserStats() {
        Map<String, Long> stats = new HashMap<>();
        LocalDateTime now = LocalDateTime.now();
        LocalDateTime sixMonthsAgo = now.minus(6, ChronoUnit.MONTHS);

        // Get all users created in the last 6 months
        userRepository.findAll().stream()
                .filter(user -> user.getCreatedAt().isAfter(sixMonthsAgo))
                .forEach(user -> {
                    String monthYear = user.getCreatedAt().getMonth() + " " + user.getCreatedAt().getYear();
                    stats.merge(monthYear, 1L, Long::sum);
                });

        return stats;
    }

    private Map<String, Long> getViewStats() {
        Map<String, Long> stats = new HashMap<>();
        LocalDateTime now = LocalDateTime.now();
        LocalDateTime sevenDaysAgo = now.minus(7, ChronoUnit.DAYS);

        // Get all articles updated in the last 7 days
        articleRepository.findAll().stream()
                .filter(article -> article.getUpdatedAt().isAfter(sevenDaysAgo))
                .forEach(article -> {
                    String date = article.getUpdatedAt().toLocalDate().toString();
                    stats.merge(date, article.getViewCount(), Long::sum);
                });

        return stats;
    }
} 